#include "Vault_u.h"
#include <errno.h>

typedef struct ms_initVault_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
} ms_initVault_t;

typedef struct ms_uninitVault_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
} ms_uninitVault_t;

typedef struct ms_encrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_encrypt_t;

typedef struct ms_encrypt_size_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	int ms_buf_len;
} ms_encrypt_size_t;

typedef struct ms_encryptex_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	const int* ms_value_lens;
	const int* ms_value_types;
	int ms_value_count;
	char* ms_out_buf;
	int ms_out_buf_size;
	int* ms_out_value_lens;
} ms_encryptex_t;

typedef struct ms_decrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_decrypt_t;

typedef struct ms_public_key_encrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_public_key_encrypt_t;

typedef struct ms_private_key_decrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_private_key_decrypt_t;

typedef struct ms_private_key_encrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_private_key_encrypt_t;

typedef struct ms_public_key_decrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_public_key_decrypt_t;

typedef struct ms_sign_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_sign_t;

typedef struct ms_sha256_encrytp_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_sha256_encrytp_t;

typedef struct ms_crypto_key_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	char* ms_key;
	int ms_key_len;
} ms_crypto_key_t;

typedef struct ms_sgx_oc_cpuidex_t {
	int* ms_cpuinfo;
	int ms_leaf;
	int ms_subleaf;
} ms_sgx_oc_cpuidex_t;

typedef struct ms_sgx_thread_wait_untrusted_event_ocall_t {
	int ms_retval;
	const void* ms_self;
} ms_sgx_thread_wait_untrusted_event_ocall_t;

typedef struct ms_sgx_thread_set_untrusted_event_ocall_t {
	int ms_retval;
	const void* ms_waiter;
} ms_sgx_thread_set_untrusted_event_ocall_t;

typedef struct ms_sgx_thread_setwait_untrusted_events_ocall_t {
	int ms_retval;
	const void* ms_waiter;
	const void* ms_self;
} ms_sgx_thread_setwait_untrusted_events_ocall_t;

typedef struct ms_sgx_thread_set_multiple_untrusted_events_ocall_t {
	int ms_retval;
	const void** ms_waiters;
	size_t ms_total;
} ms_sgx_thread_set_multiple_untrusted_events_ocall_t;

typedef struct ms_ocall_get_string_t {
	char* ms_buf;
	int ms_len;
} ms_ocall_get_string_t;

typedef struct ms_ocall_print_string_t {
	const char* ms_string;
} ms_ocall_print_string_t;

typedef struct ms_ocall_log_info_t {
	const char* ms_buf;
} ms_ocall_log_info_t;

typedef struct ms_ocall_log_warning_t {
	const char* ms_buf;
} ms_ocall_log_warning_t;

typedef struct ms_ocall_log_error_t {
	const char* ms_buf;
} ms_ocall_log_error_t;

typedef struct ms_ocall_log_fatal_t {
	const char* ms_buf;
} ms_ocall_log_fatal_t;

typedef struct ms_ocall_fopen_t {
	int ms_retval;
	_int64* ms_file;
	const char* ms_file_name;
	const char* ms_mode;
} ms_ocall_fopen_t;

typedef struct ms_ocall_fclose_t {
	int ms_retval;
	_int64 ms_file;
} ms_ocall_fclose_t;

typedef struct ms_ocall_fputs_t {
	int ms_retval;
	_int64 ms_file;
	const char* ms_buf;
} ms_ocall_fputs_t;

typedef struct ms_ocall_fseek_t {
	int ms_retval;
	_int64 ms_file;
	long int ms_offset;
	int ms_origin;
} ms_ocall_fseek_t;

typedef struct ms_ocall_ftell_t {
	long int ms_retval;
	_int64 ms_file;
} ms_ocall_ftell_t;

typedef struct ms_ocall_fread_t {
	size_t ms_retval;
	_int64 ms_file;
	void* ms_buf;
	int ms_buf_len;
	size_t ms_element_size;
	size_t ms_element_count;
} ms_ocall_fread_t;

typedef struct ms_ocall_fgets_t {
	char* ms_retval;
	_int64 ms_file;
	char* ms_buf;
	int ms_buf_len;
} ms_ocall_fgets_t;

typedef struct ms_ocall_is_dir_exsit_t {
	int ms_retval;
	const char* ms_dri_name;
} ms_ocall_is_dir_exsit_t;

typedef struct ms_ocall_make_dir_t {
	int ms_retval;
	const char* ms_dir_name;
} ms_ocall_make_dir_t;

typedef struct ms_u_sgxssl_ftime64_t {
	void* ms_timeptr;
	uint32_t ms_timeb64Len;
} ms_u_sgxssl_ftime64_t;

static sgx_status_t SGX_CDECL Vault_sgx_oc_cpuidex(void* pms)
{
	ms_sgx_oc_cpuidex_t* ms = SGX_CAST(ms_sgx_oc_cpuidex_t*, pms);
	sgx_oc_cpuidex(ms->ms_cpuinfo, ms->ms_leaf, ms->ms_subleaf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_sgx_thread_wait_untrusted_event_ocall(void* pms)
{
	ms_sgx_thread_wait_untrusted_event_ocall_t* ms = SGX_CAST(ms_sgx_thread_wait_untrusted_event_ocall_t*, pms);
	ms->ms_retval = sgx_thread_wait_untrusted_event_ocall(ms->ms_self);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_sgx_thread_set_untrusted_event_ocall(void* pms)
{
	ms_sgx_thread_set_untrusted_event_ocall_t* ms = SGX_CAST(ms_sgx_thread_set_untrusted_event_ocall_t*, pms);
	ms->ms_retval = sgx_thread_set_untrusted_event_ocall(ms->ms_waiter);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_sgx_thread_setwait_untrusted_events_ocall(void* pms)
{
	ms_sgx_thread_setwait_untrusted_events_ocall_t* ms = SGX_CAST(ms_sgx_thread_setwait_untrusted_events_ocall_t*, pms);
	ms->ms_retval = sgx_thread_setwait_untrusted_events_ocall(ms->ms_waiter, ms->ms_self);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_sgx_thread_set_multiple_untrusted_events_ocall(void* pms)
{
	ms_sgx_thread_set_multiple_untrusted_events_ocall_t* ms = SGX_CAST(ms_sgx_thread_set_multiple_untrusted_events_ocall_t*, pms);
	ms->ms_retval = sgx_thread_set_multiple_untrusted_events_ocall(ms->ms_waiters, ms->ms_total);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_get_string(void* pms)
{
	ms_ocall_get_string_t* ms = SGX_CAST(ms_ocall_get_string_t*, pms);
	ocall_get_string(ms->ms_buf, ms->ms_len);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_print_string(void* pms)
{
	ms_ocall_print_string_t* ms = SGX_CAST(ms_ocall_print_string_t*, pms);
	ocall_print_string(ms->ms_string);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_log_info(void* pms)
{
	ms_ocall_log_info_t* ms = SGX_CAST(ms_ocall_log_info_t*, pms);
	ocall_log_info(ms->ms_buf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_log_warning(void* pms)
{
	ms_ocall_log_warning_t* ms = SGX_CAST(ms_ocall_log_warning_t*, pms);
	ocall_log_warning(ms->ms_buf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_log_error(void* pms)
{
	ms_ocall_log_error_t* ms = SGX_CAST(ms_ocall_log_error_t*, pms);
	ocall_log_error(ms->ms_buf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_log_fatal(void* pms)
{
	ms_ocall_log_fatal_t* ms = SGX_CAST(ms_ocall_log_fatal_t*, pms);
	ocall_log_fatal(ms->ms_buf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_fopen(void* pms)
{
	ms_ocall_fopen_t* ms = SGX_CAST(ms_ocall_fopen_t*, pms);
	ms->ms_retval = ocall_fopen(ms->ms_file, ms->ms_file_name, ms->ms_mode);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_fclose(void* pms)
{
	ms_ocall_fclose_t* ms = SGX_CAST(ms_ocall_fclose_t*, pms);
	ms->ms_retval = ocall_fclose(ms->ms_file);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_fputs(void* pms)
{
	ms_ocall_fputs_t* ms = SGX_CAST(ms_ocall_fputs_t*, pms);
	ms->ms_retval = ocall_fputs(ms->ms_file, ms->ms_buf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_fseek(void* pms)
{
	ms_ocall_fseek_t* ms = SGX_CAST(ms_ocall_fseek_t*, pms);
	ms->ms_retval = ocall_fseek(ms->ms_file, ms->ms_offset, ms->ms_origin);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_ftell(void* pms)
{
	ms_ocall_ftell_t* ms = SGX_CAST(ms_ocall_ftell_t*, pms);
	ms->ms_retval = ocall_ftell(ms->ms_file);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_fread(void* pms)
{
	ms_ocall_fread_t* ms = SGX_CAST(ms_ocall_fread_t*, pms);
	ms->ms_retval = ocall_fread(ms->ms_file, ms->ms_buf, ms->ms_buf_len, ms->ms_element_size, ms->ms_element_count);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_fgets(void* pms)
{
	ms_ocall_fgets_t* ms = SGX_CAST(ms_ocall_fgets_t*, pms);
	ms->ms_retval = ocall_fgets(ms->ms_file, ms->ms_buf, ms->ms_buf_len);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_is_dir_exsit(void* pms)
{
	ms_ocall_is_dir_exsit_t* ms = SGX_CAST(ms_ocall_is_dir_exsit_t*, pms);
	ms->ms_retval = ocall_is_dir_exsit(ms->ms_dri_name);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_ocall_make_dir(void* pms)
{
	ms_ocall_make_dir_t* ms = SGX_CAST(ms_ocall_make_dir_t*, pms);
	ms->ms_retval = ocall_make_dir(ms->ms_dir_name);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Vault_u_sgxssl_ftime64(void* pms)
{
	ms_u_sgxssl_ftime64_t* ms = SGX_CAST(ms_u_sgxssl_ftime64_t*, pms);
	u_sgxssl_ftime64(ms->ms_timeptr, ms->ms_timeb64Len);

	return SGX_SUCCESS;
}

static const struct {
	size_t nr_ocall;
	void * func_addr[21];
} ocall_table_Vault = {
	21,
	{
		(void*)(uintptr_t)Vault_sgx_oc_cpuidex,
		(void*)(uintptr_t)Vault_sgx_thread_wait_untrusted_event_ocall,
		(void*)(uintptr_t)Vault_sgx_thread_set_untrusted_event_ocall,
		(void*)(uintptr_t)Vault_sgx_thread_setwait_untrusted_events_ocall,
		(void*)(uintptr_t)Vault_sgx_thread_set_multiple_untrusted_events_ocall,
		(void*)(uintptr_t)Vault_ocall_get_string,
		(void*)(uintptr_t)Vault_ocall_print_string,
		(void*)(uintptr_t)Vault_ocall_log_info,
		(void*)(uintptr_t)Vault_ocall_log_warning,
		(void*)(uintptr_t)Vault_ocall_log_error,
		(void*)(uintptr_t)Vault_ocall_log_fatal,
		(void*)(uintptr_t)Vault_ocall_fopen,
		(void*)(uintptr_t)Vault_ocall_fclose,
		(void*)(uintptr_t)Vault_ocall_fputs,
		(void*)(uintptr_t)Vault_ocall_fseek,
		(void*)(uintptr_t)Vault_ocall_ftell,
		(void*)(uintptr_t)Vault_ocall_fread,
		(void*)(uintptr_t)Vault_ocall_fgets,
		(void*)(uintptr_t)Vault_ocall_is_dir_exsit,
		(void*)(uintptr_t)Vault_ocall_make_dir,
		(void*)(uintptr_t)Vault_u_sgxssl_ftime64,
	}
};

sgx_status_t initVault(sgx_enclave_id_t eid, int* retval, const char* id)
{
	sgx_status_t status;
	ms_initVault_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	status = sgx_ecall(eid, 0, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t uninitVault(sgx_enclave_id_t eid, int* retval, const char* id)
{
	sgx_status_t status;
	ms_uninitVault_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	status = sgx_ecall(eid, 1, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t encrypt(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_encrypt_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 2, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t encrypt_size(sgx_enclave_id_t eid, int* retval, const char* id, int buf_len)
{
	sgx_status_t status;
	ms_encrypt_size_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_buf_len = buf_len;
	status = sgx_ecall(eid, 3, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t encryptex(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, const int* value_lens, const int* value_types, int value_count, char* out_buf, int out_buf_size, int* out_value_lens)
{
	sgx_status_t status;
	ms_encryptex_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_value_lens = value_lens;
	ms.ms_value_types = value_types;
	ms.ms_value_count = value_count;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	ms.ms_out_value_lens = out_value_lens;
	status = sgx_ecall(eid, 4, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t decrypt(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_decrypt_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 5, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t public_key_encrypt(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_public_key_encrypt_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 6, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t private_key_decrypt(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_private_key_decrypt_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 7, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t private_key_encrypt(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_private_key_encrypt_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 8, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t public_key_decrypt(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_public_key_decrypt_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 9, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t sign(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_sign_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 10, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t sha256_encrytp(sgx_enclave_id_t eid, int* retval, const char* id, const char* in_buf, int in_buf_len, char* out_buf, int out_buf_size)
{
	sgx_status_t status;
	ms_sha256_encrytp_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_in_buf = in_buf;
	ms.ms_in_buf_len = in_buf_len;
	ms.ms_out_buf = out_buf;
	ms.ms_out_buf_size = out_buf_size;
	status = sgx_ecall(eid, 11, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t crypto_key(sgx_enclave_id_t eid, int* retval, const char* id, char* key, int key_len)
{
	sgx_status_t status;
	ms_crypto_key_t ms;
	ms.ms_id = id;
	ms.ms_id_len = id ? strlen(id) + 1 : 0;
	ms.ms_key = key;
	ms.ms_key_len = key_len;
	status = sgx_ecall(eid, 12, &ocall_table_Vault, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

